package com.gzc.just.play.last.war.centralserver.service;

import com.google.protobuf.ByteString;
import com.gzc.just.play.last.war.centralserver.cache.StatusCache;
import com.gzc.just.play.last.war.centralserver.repository.StatusRepository;
import com.gzc.just.play.last.war.centralserver.service.persistence.AsyncPersistenceManager;
import com.gzc.just.play.last.war.centralserver.user.model.User;
import com.gzc.just.play.last.war.common.net.NetUtils;
import com.gzc.just.play.last.war.protobuf.cs.cstogs.CSToGS;
import com.gzc.just.play.last.war.protobuf.gc.gctocs.GCToCS;
import com.gzc.just.play.last.war.protobuf.gs.gstogc.GSToGC;
import io.netty.channel.ChannelHandlerContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import jakarta.annotation.PostConstruct;

import java.time.LocalDateTime;
import java.time.ZoneOffset;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 用户服务
 * 管理用户信息、状态和好友关系
 */
@Service("userStatusService")
public class UserStatusService {
    private static final Logger logger = LoggerFactory.getLogger(UserStatusService.class);
    
    private final StatusRepository statusRepository;
    private final StatusCache statusCache;
    private final AsyncPersistenceManager asyncPersistenceManager;

    // 用户名索引 (Name -> UserID)
    // In a distributed system, this should also be in Redis
    private final Map<String, Long> nameIndex = new ConcurrentHashMap<>();

    // 用户好友关系（用户ID -> 好友ID集合）
    // TODO: Move to FriendRepository/FriendService with persistence
    private final Map<Long, Set<Long>> userFriends = new ConcurrentHashMap<>();
    
    // 在线用户（用户ID -> 登录时间）
    private final Map<Long, Long> onlineUsers = new ConcurrentHashMap<>();
    
    public UserStatusService(StatusRepository statusRepository, 
                           StatusCache statusCache,
                           AsyncPersistenceManager asyncPersistenceManager) {
        this.statusRepository = statusRepository;
        this.statusCache = statusCache;
        this.asyncPersistenceManager = asyncPersistenceManager;
    }

    @PostConstruct
    public void init() {
        // Initialize name index from DB? Or lazy load?
        // For All-in-One, maybe we want to load some initial data if empty?
        logger.info("UserService initialized");
    }
    
    /**
     * 处理用户登录请求 (Central Server Core Logic)
     */
    public void handleUserLogin(int nsid, GCToCS.Login login, ChannelHandlerContext gateCtx) {
        String name = login.getName();
        int platform = login.getPlatform(); // Assuming this is used for something
        
        logger.info("Processing login for user: {}, platform: {}, nsid: {}", name, platform, nsid);
        
        User user = findUserByName(name);
        
        if (user != null) {
            // 老用户
            logger.info("User found: ID={}, Name={}", user.getUserId(), name);
        } else {
            // 新用户 - 注册逻辑
            user = new User();
            user.setUsername(name);
            user.setNickname("Nick_" + name);
            user.setPasswordHash("default_hash"); // Should be proper hash
            user.setLevel(1);
            user.setExp(0L);
            user.setGold(0L);
            user.setGems(0L);
            user.setPower(100);
            user.setMaxPower(100L);
            user.setCreateTime(LocalDateTime.now());
            user.setUpdateTime(LocalDateTime.now());
            user.setStatus(User.UserStatus.ONLINE);
            
            // Save to DB (Sync for first creation to get ID)
            user = statusRepository.save(user);
            
            // Update Cache
            statusCache.put(user);
            nameIndex.put(name, user.getUserId());
            
            // Initialize friends
            userFriends.put(user.getUserId(), new HashSet<>());
            
            logger.info("New user registered: ID={}, Name={}", user.getUserId(), name);
        }
        
        // 设置在线状态
        setOnline(user.getUserId());
        
        // 发送登录成功消息给客户端 (UserBaseInfo)
        sendLoginSuccess(gateCtx, nsid, user);
    }

    private User findUserByName(String name) {
        // 1. Try local index
        Long userId = nameIndex.get(name);
        if (userId != null) {
            return getUser(userId);
        }
        
        // 2. Try DB by name
        Optional<User> userOpt = statusRepository.findByUsername(name);
        if (userOpt.isPresent()) {
            User user = userOpt.get();
            statusCache.put(user);
            nameIndex.put(name, user.getUserId());
            return user;
        }
        
        return null;
    }

    private User getUser(Long userId) {
        // 1. Try Cache
        Optional<User> cachedUser = statusCache.get(userId);
        if (cachedUser.isPresent()) {
            return cachedUser.get();
        }
        
        // 2. Try DB
        Optional<User> dbUser = statusRepository.findById(userId);
        if (dbUser.isPresent()) {
            statusCache.put(dbUser.get());
            return dbUser.get();
        }
        
        return null;
    }

    private void sendLoginSuccess(ChannelHandlerContext gateCtx, int nsid, User user) {
        try {
            // 1. 构造 GSToGC.UserBaseInfo
            GSToGC.UserBaseInfo userBaseInfo = GSToGC.UserBaseInfo.newBuilder()
                .setMsgid(GSToGC.MsgID.eMsgToGCFromGS_NotifyUserBaseInfo)
                .setGuid(user.getUserId())
                .setName(user.getUsername())
                .setNickname(user.getNickname())
                .setHeadid(1) // TODO: Add headId to User entity
                .setSex(1)    // TODO: Add sex to User entity
                .setLevel(user.getLevel())
                .build();
                
            // 2. 构造 CSToGS.OrderPostToGC (包装消息)
            CSToGS.OrderPostToGC.UserNetInfo userNetInfo = CSToGS.OrderPostToGC.UserNetInfo.newBuilder()
                .setGcnid(nsid)
                .build();
                
            CSToGS.OrderPostToGC order = CSToGS.OrderPostToGC.newBuilder()
                .setMsgid(CSToGS.MsgID.eMsgToGSFromCS_OrderPostToGC)
                .addUsernetinfo(userNetInfo)
                .setOthermsgid(GSToGC.MsgID.eMsgToGCFromGS_NotifyUserBaseInfo_VALUE) 
                .setOthermsg(userBaseInfo.toByteString())
                .build();
            
            // 3. 发送给 Gate Server
            NetUtils.sendMsg(gateCtx.channel(), 24581, order); // 24581 = OrderPostToGC
            
            logger.info("Sent login success response to Gate for user {}", user.getUsername());
            
        } catch (Exception e) {
            logger.error("Failed to send login success response", e);
        }
    }
    
    /**
     * 获取用户信息 (Compatibility method)
     */
    public Map<String, Object> getUserInfo(Long userId) {
        User user = getUser(userId);
        if (user == null) {
            return null;
        }
        
        Map<String, Object> info = new HashMap<>();
        info.put("userId", user.getUserId());
        info.put("name", user.getUsername());
        info.put("email", "test@example.com"); // Placeholder
        info.put("level", user.getLevel());
        info.put("score", user.getRankScore());
        info.put("createTime", user.getCreateTime().toInstant(ZoneOffset.UTC).toEpochMilli());
        info.put("status", onlineUsers.containsKey(userId) ? "online" : "offline");
        info.put("location", "login"); // Placeholder
        info.put("gameMode", "normal"); // Placeholder
        info.put("clan", "None"); // Placeholder
        info.put("avatar", "default.png"); // Placeholder
        info.put("online", onlineUsers.containsKey(userId));
        info.put("loginTime", onlineUsers.get(userId));
        
        return info;
    }
    
    /**
     * 获取用户对象
     */
    public User getUserInfoObject(Long userId) {
        User user = getUser(userId);
        if (user != null) {
            user.setIsOnline(onlineUsers.containsKey(userId));
            user.setStatus(onlineUsers.containsKey(userId) ? User.UserStatus.ONLINE : User.UserStatus.OFFLINE);
        }
        return user;
    }
    
    /**
     * 更新用户状态
     */
    public boolean updateUserStatus(Long userId, Map<String, Object> statusInfo) {
        User user = getUser(userId);
        if (user == null) {
            logger.warn("User {} not found for status update", userId);
            return false;
        }
        
        boolean changed = false;
        // 更新状态
        if (statusInfo.containsKey("status")) {
            String statusStr = statusInfo.get("status").toString();
            try {
                User.UserStatus newStatus = User.UserStatus.valueOf(statusStr.toUpperCase());
                user.setStatus(newStatus);
                changed = true;
            } catch (IllegalArgumentException e) {
                // ignore
            }
            
            if ("online".equals(statusStr)) {
                onlineUsers.put(userId, System.currentTimeMillis());
            } else if ("offline".equals(statusStr)) {
                onlineUsers.remove(userId);
            }
        }
        
        // Handle other fields if User entity supports them
        
        if (changed) {
            saveUser(user);
        }
        
        logger.debug("Updated status for user: {}", userId);
        return true;
    }

    private void saveUser(User user) {
        // Update Cache
        statusCache.put(user);
        // Async Persist
        asyncPersistenceManager.submit(user);
    }
    
    /**
     * 获取在线好友列表
     */
    public Map<Long, Map<String, Object>> getOnlineFriends(Long userId) {
        Set<Long> friendIds = userFriends.get(userId);
        if (friendIds == null) {
            return new HashMap<>();
        }
        
        Map<Long, Map<String, Object>> onlineFriends = new HashMap<>();
        
        for (Long friendId : friendIds) {
            if (onlineUsers.containsKey(friendId)) {
                Map<String, Object> friendInfo = getUserInfo(friendId);
                if (friendInfo != null) {
                    onlineFriends.put(friendId, friendInfo);
                }
            }
        }
        
        return onlineFriends;
    }
    
    /**
     * 获取所有好友列表
     */
    public Map<Long, Map<String, Object>> getAllFriends(Long userId) {
        Set<Long> friendIds = userFriends.get(userId);
        if (friendIds == null) {
            return new HashMap<>();
        }
        
        Map<Long, Map<String, Object>> friends = new HashMap<>();
        
        for (Long friendId : friendIds) {
            Map<String, Object> friendInfo = getUserInfo(friendId);
            if (friendInfo != null) {
                friends.put(friendId, friendInfo);
            }
        }
        
        return friends;
    }
    
    /**
     * 添加好友关系
     */
    public boolean addFriend(Long userId, Long friendId) {
        if (getUser(userId) == null || getUser(friendId) == null) {
            return false;
        }
        
        userFriends.computeIfAbsent(userId, k -> new HashSet<>()).add(friendId);
        userFriends.computeIfAbsent(friendId, k -> new HashSet<>()).add(userId);
        
        logger.info("Added friendship between user {} and {}", userId, friendId);
        return true;
    }
    
    /**
     * 删除好友关系
     */
    public boolean removeFriend(Long userId, Long friendId) {
        if (getUser(userId) == null || getUser(friendId) == null) {
            return false;
        }
        
        if (userFriends.containsKey(userId)) userFriends.get(userId).remove(friendId);
        if (userFriends.containsKey(friendId)) userFriends.get(friendId).remove(userId);
        
        logger.info("Removed friendship between user {} and {}", userId, friendId);
        return true;
    }
    
    /**
     * 设置用户在线状态
     */
    public void setOnline(Long userId) {
        onlineUsers.put(userId, System.currentTimeMillis());
        User user = getUser(userId);
        if (user != null) {
            user.setStatus(User.UserStatus.ONLINE);
            saveUser(user);
        }
        logger.debug("User {} is now online", userId);
    }
    
    /**
     * 设置用户离线状态
     */
    public void setOffline(Long userId) {
        onlineUsers.remove(userId);
        User user = getUser(userId);
        if (user != null) {
            user.setStatus(User.UserStatus.OFFLINE);
            saveUser(user);
        }
        logger.debug("User {} is now offline", userId);
    }
    
    /**
     * 获取在线用户数量
     */
    public int getOnlineUserCount() {
        return onlineUsers.size();
    }
    
    /**
     * 获取所有用户数量
     */
    public int getTotalUserCount() {
        // approximate, only counts cached/known
        return nameIndex.size(); // or better query repo count
    }
    
    /**
     * 用户登录 (Simple version)
     */
    public Map<String, Object> login(Object request) {
        // Use handleUserLogin for real logic
        return new HashMap<>();
    }
    
    /**
     * 用户注册
     */
    public Map<String, Object> register(Object request) {
        return new HashMap<>();
    }
    
    /**
     * 用户登出
     */
    public void logout(Long userId) {
        setOffline(userId);
    }
    
    /**
     * 更新用户信息
     */
    public User updateUserInfo(User user) {
        saveUser(user);
        return user;
    }
    
    /**
     * 增加用户经验
     */
    public void addUserExp(Long userId, long amount) {
        User user = getUser(userId);
        if (user != null) {
            user.addExp(amount);
            saveUser(user);
            logger.info("Added {} exp to user {}", amount, userId);
        }
    }
    
    /**
     * 增加用户金币
     */
    public void addUserGold(Long userId, long amount) {
        User user = getUser(userId);
        if (user != null) {
            user.addGold(amount);
            saveUser(user);
            logger.info("Added {} gold to user {}", amount, userId);
        }
    }
    
    /**
     * 增加用户钻石
     */
    public void addUserGems(Long userId, long amount) {
        User user = getUser(userId);
        if (user != null) {
            user.addGems(amount);
            saveUser(user);
            logger.info("Added {} gems to user {}", amount, userId);
        }
    }
    
    /**
     * 恢复用户体力
     */
    public void recoverUserPower(Long userId, int amount) {
        User user = getUser(userId);
        if (user != null) {
            user.recoverPower(amount);
            saveUser(user);
            logger.info("Recovered {} power for user {}", amount, userId);
        }
    }
    
    /**
     * 消耗用户体力
     */
    public boolean consumeUserPower(Long userId, int amount) {
        User user = getUser(userId);
        if (user != null) {
            boolean success = user.consumePower(amount);
            if (success) {
                saveUser(user);
                logger.info("Consumed {} power for user {}", amount, userId);
            }
            return success;
        }
        return false;
    }
    
    /**
     * 获取排名前N的玩家
     */
    public List<User> getTopPlayers(int limit) {
        // TODO: This should be a DB query
        return new ArrayList<>();
    }
    
    /**
     * 检查用户是否在线
     */
    public boolean isUserOnline(Long userId) {
        return onlineUsers.containsKey(userId);
    }
}
